/**************************************************************************** 
* 
* Copyright (c) 2022  C*Core -   All Rights Reserved  
* 
* THIS SOFTWARE IS DISTRIBUTED "AS IS," AND ALL WARRANTIES ARE DISCLAIMED, 
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* 
* PROJECT     : CCFC2011BC           
* DESCRIPTION : CCFC2011BC MPU low level drivers Code  
* HISTORY     : 2022
* @file     mpu_lld.c
* @version  3.0
* @date     2022-10-27
* @brief    Initial version.
*
*****************************************************************************/

#ifndef MPU_LLD_H_
#define MPU_LLD_H_
#include "CCFC2011BC.h"
#include "sys.h"
#include "common.h"
#include "typedefs.h"

/************************************************************************
 *    MPU Control/Error Status Register (MPU_CESR)
 *    Configuration parameter
 ************************************************************************/
/* CESR(32 bits), Default: 0x00814000 */
#define CESR_MPU_DIS    (0x00000000u)
#define CESR_MPU_EN     (0x00000001u)
#define CESR_SPERR2     (0x20000000u)
#define CESR_SPERR1     (0x40000000u)
#define CESR_SPERR0     (0x80000000u)
#define CESR_SPERR_All  (0xE0000000u)

/* R/W: Slave Port Error number(3 bits) */
#define SPERR_NO_ERROR  (0u)   /* Default */
#define SPERR2_PER_BUS  (1u)   /* IPS peripheral bus slave port */
#define SPERR1_RAM      (2u)   /* System RAM controller slave port */
#define SPERR0_FLASH    (4u)   /* Flash memory controller slave port */


/* RO: Hardware Revision Level(4 bits) */
#define HRL_REV0    (0u)
#define HRL_REV1    (1u)   /* Default, maybe will change */
#define HRL_REV2    (2u)
#define HRL_REV3    (3u)
#define HRL_REV4    (4u)
#define HRL_REV5    (5u)
#define HRL_REV6    (6u)
#define HRL_REV7    (7u)
#define HRL_REV8    (8u)
#define HRL_REV9    (9u)
#define HRL_REV10   (10u)
#define HRL_REV11   (11u)
#define HRL_REV12   (12u)
#define HRL_REV13   (13u)
#define HRL_REV14   (14u)
#define HRL_REV15   (15u)

/* RO: Number of Slave Ports[1-8](4 bits) */
#define NSP_1   (1u)
#define NSP_2   (2u)
#define NSP_3   (3u)
#define NSP_4   (4u)   /* Default, one was turned off, actually: NSP_3 */
#define NSP_5   (5u)
#define NSP_6   (6u)
#define NSP_7   (7u)
#define NSP_8   (8u)

/* RO: Number of Region Descriptors(4 bits) */
#define NRGD_8  (0u)   /* Default */
#define NRGD_12 (1u)
#define NRGD_16 (2u)

/* R/W: MPU Valid(1 bit) */
#define VLD_DIS (0u)   /* Default */
#define VLD_EN  (1u)


/************************************************************************
 *    MPU Error Detail Register, Slave Port n (MPU_EDRn)
 *    Configuration parameter
 ************************************************************************/
/* RO: Error Attributes(3 bits)
 * For non-core bus masters, the access attribute information is 
 * typically wired to supervisor, data (0b011). */
#define EATTR_USER_INSTR    (0u)   /* User mode, instruction access        */
#define EATTR_USER_DATA     (1u)   /* User mode, data access               */
#define EATTR_SUPER_INSTR   (2u)   /* Supervisor mode, instruction access  */
#define EATTR_SUPER_DATA    (3u)   /* Supervisor mode, data access         */
#define EATTR_RESERVED_0    (4u)
#define EATTR_RESERVED_1    (5u)
#define EATTR_RESERVED_2    (6u)
#define EATTR_RESERVED_3    (7u)

/* RO: Error Read/Write(1 bit) */
#define ERW_READ    (0u)
#define ERW_WRITE   (1u)



/************************************************************************
 *    MPU Region Descriptor n (MPU_RGDn)
 *    Configuration parameter
 ************************************************************************/
/* MPU Region Descriptor Number: NRGD_8 */
#define MPU_RGD0    (0u)
#define MPU_RGD1    (1u)
#define MPU_RGD2    (2u)
#define MPU_RGD3    (3u)
#define MPU_RGD4    (4u)
#define MPU_RGD5    (5u)
#define MPU_RGD6    (6u)
#define MPU_RGD7    (7u)

/************************************************************************
 *    MPU Region Descriptor n, Word 2(MPU_RGDn.Word2)
 *    Configuration parameter
 ************************************************************************/
/* Bus master 4~7 read/write enable */
#define M4WE    (0x01000000u)
#define M4RE    (0x02000000u)
#define M5WE    (0x04000000u)
#define M5RE    (0x08000000u)
#define M6WE    (0x10000000u)
#define M6RE    (0x20000000u)
#define M7WE    (0x40000000u)
#define M7RE    (0x80000000u)

/* Bus master 3 process identifier enable */
#define M3PE_DIS    (0x00000000u)
#define M3PE        (0x00800000u)

/* Bus master 3 supervisor mode access control */
#define M3SM_RWX    (0x00000000u)
#define M3SM_RX     (0x00200000u)
#define M3SM_RW     (0x00400000u)
#define M3SM_EQ_M0UM    (0x00600000u)   /* Same access controls: M3SM = M3UM. */

/* Bus master 3 user mode access control */
#define M3UM_X      (0x00040000u)
#define M3UM_W      (0x00080000u)
#define M3UM_WX     (0x000C0000u)
#define M3UM_R      (0x00100000u)
#define M3UM_RX     (0x00140000u)
#define M3UM_RW     (0x00180000u)
#define M3UM_RWX    (0x001C0000u)

/* Bus master 2 supervisor mode access control */
#define M2PE_DIS    (0x00000000u)
#define M2PE        (0x00020000u)

/* Bus master 2 supervisor mode access control */
#define M2SM_RW_        (0x00000000u)   /* = M2SM_RW */
#define M2SM_R          (0x00008000u)
#define M2SM_RW         (0x00010000u)
#define M2SM_EQ_M2UM    (0x00018000u)   /* Same access controls: M2SM = M2UM. */

/* Bus master 2 user mode access control */
#define M2UM_W      (0x00002000u)
#define M2UM_R      (0x00004000u)
#define M2UM_RW     (0x00006000u)

#define M0PE_DIS    (0x00000000u)
#define M0PE        (0x00000020u)

/* Bus master 0 user mode access control */
#define M0UM_NON    (0x00000000u)
#define M0UM_X      (0x00000001u)
#define M0UM_W      (0x00000002u)
#define M0UM_WX     (0x00000003u)
#define M0UM_R      (0x00000004u)
#define M0UM_RX     (0x00000005u)
#define M0UM_RW     (0x00000006u)
#define M0UM_RWX    (0x00000007u)

/* Bus master 0 supervisor mode access control */
#define M0SM_RWX        (0x00000000u)
#define M0SM_RX         (0x00000008u)
#define M0SM_RW         (0x00000010u)
#define M0SM_EQ_M0UM    (0x00000018u)   /* Same access controls: M0SM = M0UM. */
#define M0SM_NON        ((M0SM_EQ_M0UM|M0UM_NON))
#define M0SM_X          ((M0SM_EQ_M0UM|M0UM_X))
#define M0SM_W          ((M0SM_EQ_M0UM|M0UM_W))
#define M0SM_WX         ((M0SM_EQ_M0UM|M0UM_WX))
#define M0SM_R          ((M0SM_EQ_M0UM|M0UM_R))
#define M0SM_RX_        ((M0SM_EQ_M0UM|M0UM_RX))   /* = M0SM_RX */
#define M0SM_RW_        ((M0SM_EQ_M0UM|M0UM_RW))   /* = M0SM_RW */
#define M0SM_RWX_       ((M0SM_EQ_M0UM|M0UM_RWX))  /* = M0SM_RWX */

/************************************************************************
 *    MPU Region Descriptor n, Word 3(MPU_RGDn.Word3)
 *    Configuration parameter
 ************************************************************************/
#define RGDn_INVALID    (0x00000000u)
#define RGDn_VALID      (0x00000001u)



/************************************************************************
 *    MPU Control/Error Status Register (MPU_CESR)
 *    Access: Read/Partial Write
 ************************************************************************/
/* @brief   Read: MPU Control/Error Status Register.
 * @note    bit[0:31] = {SPERR[0:2], RESERVED0[3:11], HRL[12:15],
 *          NSP[16:19], NRGD[20:23], RESERVED1[24:30], VLD[31]};
 * @ret_val MPU_CESR_t */
#define MPU_GET_CESR()                    (MPU.CESR.R) /* PRQA S 3472 */

/* @ret_val CESR_SPERRn_t */
#define MPU_GET_CESR_SPERR()              (MPU.CESR.B.SPERR)

/* @ret_val CESR_HRL_t */
#define MPU_GET_CESR_HRL()                (MPU.CESR.B.HRL)

/* @ret_val CESR_NSP_t */
#define MPU_GET_CESR_NSP()                (MPU.CESR.B.NSP)

/* @ret_val CESR_NRGD_t */
#define MPU_GET_CESR_NRGD()               (MPU.CESR.B.NRGD)

/* @ret_val CESR_VLD_t */
#define MPU_GET_CESR_VLD()                (MPU.CESR.B.VLD)

/* @brief MPU Control/Error Status Register (MPU_CESR) set.
 * @note  The MPU_CESR provides one byte of error status plus three bytes
 *          of configuration information.
 *        A global MPU enable/disable bit is also included in this register.
 * @param val: MPU_CESR_t.
 * */
#define MPU_CESR_SET(val)          (MPU.CESR.R = (val)) /* PRQA S 3472 */

/* @brief Slave Port n Error(write 1 to clear),
 *          where the slave port number matches the bit number.
 * @param val: CESR_SPERRn_t, write to clear.
 * */
#define MPU_CESR_SPERR_SET(val)    (MPU.CESR.B.SPERR = (val))

/* @brief Write Valid bit.
 * @note  This bit provides a global enable/disable for the MPU.
 *        While the MPU is disabled, all accesses from all bus 
 *          masters are allowed.
 * @return refer: CESR_VLD_t(0: disable, 1: enable).
 * */
#define MPU_CESR_VLD_SET(val)      (MPU.CESR.B.VLD = (val))


/************************************************************************
 *    MPU Error Address Register, Slave Port n (MPU_EARn)
 *    Access: Read
 ************************************************************************/
/* @brief   Error Address(Slave Port 0/1/2).
 * @note    This field is the reference address from slave port n that 
 *           generated the access error.
 * @ret_val 32bits address.
 * */
#define MPU_GET_EAR0()                    (MPU.EAR0.R)
#define MPU_GET_EAR1()                    (MPU.EAR1.R)
#define MPU_GET_EAR2()                    (MPU.EAR2.R)


/************************************************************************
 *    MPU Error Detail Register, Slave Port n (MPU_EDRn)
 *    Access: Read
 ************************************************************************/
/* @brief   MPU Error Detail Register(Slave Port 0/1/2).
 * @note    bit[0:31] = {RESERVED[0:7], EACD[8:15], EPID[16:23], 
 *          EMN[24:27], EATTR[28:30], ERW[31]};
 * @ret_val 32bits.
 * */
#define MPU_GET_EDR0()                    (MPU.EDR0.R)
#define MPU_GET_EDR1()                    (MPU.EDR1.R)
#define MPU_GET_EDR2()                    (MPU.EDR2.R)

/* @brief Error Access Control Detail(Slave Port 0/1/2).
 * @note  This field implements one bit per region descriptor and is an 
 *          indication of the region descriptor hit logically ANDed with 
 *          the access error indication.
 * @ret_val 8bits.
 * */
#define MPU_GET_EDR0_EACD()               (MPU.EDR0.B.EACD)
#define MPU_GET_EDR1_EACD()               (MPU.EDR1.B.EACD)
#define MPU_GET_EDR2_EACD()               (MPU.EDR2.B.EACD)

/* @brief Error Process Identification(Slave Port 0/1/2).
 * @note  This field records the process identifier of the faulting 
 *          reference. The process identifier is typically driven only 
 *          by processor cores; for other bus masters, this field is 
 *          cleared.
 * @ret_val 8bits.
 * */
#define MPU_GET_EDR0_EPID()               (MPU.EDR0.B.EPID)
#define MPU_GET_EDR1_EPID()               (MPU.EDR1.B.EPID)
#define MPU_GET_EDR2_EPID()               (MPU.EDR2.B.EPID)

/* @brief Error Master Number(Slave Port 0/1/2).
 * @note  This field records the logical master number of the faulting 
 *          reference. This field is used to determine the bus master 
 *          that generated the access error.
 * @ret_val 4bits.
 * */
#define MPU_GET_EDR0_EMN()                (MPU.EDR0.B.EMN)
#define MPU_GET_EDR1_EMN()                (MPU.EDR1.B.EMN)
#define MPU_GET_EDR2_EMN()                (MPU.EDR2.B.EMN)

/* @brief Error Attributes(Slave Port 0/1/2).
 * @note  This field records attribute information about the faulting 
 *          reference.
 * @ret_val refer: EDRn_EATTR_t.
 * */
#define MPU_GET_EDR0_EATTR()              (MPU.EDR0.B.EATTR)
#define MPU_GET_EDR1_EATTR()              (MPU.EDR1.B.EATTR)
#define MPU_GET_EDR2_EATTR()              (MPU.EDR2.B.EATTR)

/* @brief Error Read/Write(Slave Port 0/1/2).
 * @note  This field signals the access type (read, write) of the 
 *          faulting reference.
 * @ret_val refer: EDRn_ERW_t.
 * */
#define MPU_GET_EDR0_ERW()                (MPU.EDR0.B.ERW)
#define MPU_GET_EDR1_ERW()                (MPU.EDR1.B.ERW)
#define MPU_GET_EDR2_ERW()                (MPU.EDR2.B.ERW)


/************************************************************************
 *    MPU Region Descriptor n (MPU_RGDn)
 * MPU Region Descriptor n, Word 0(MPU_RGDn.Word0): Start Address
 * MPU Region Descriptor n, Word 1(MPU_RGDn.Word1): End Address
 * MPU Region Descriptor n, Word 2(MPU_RGDn.Word2): Access control rights
 * MPU Region Descriptor n, Word 3(MPU_RGDn.Word3): PID
 ************************************************************************/
/************************************************************************
 *    MPU Region Descriptor n, Word 0(MPU_RGDn.Word0)
 *    Access: Read/Write
 ************************************************************************/
/* @brief WORD0: Read Start Address.
 * @param n: MPU_RGDn_t(0~7).
 * @ret_val 32bits address(Significant bits: 27 bits high).
 * */
#define MPU_GET_RGDn_WORD0(n)    (MPU.RGD[n].WORD0.R)

/************************************************************************
 *    MPU Region Descriptor n, Word 1(MPU_RGDn.Word1)
 *    Access: Read/Write
 ************************************************************************/
/* @brief WORD1: Read End Address.
 * @param n: MPU_RGDn_t(0~7).
 * @ret_val 32bits address(Significant bits: 27 bits high)
 * */
#define MPU_GET_RGDn_WORD1(n)    (MPU.RGD[n].WORD1.R)

/************************************************************************
 *    MPU Region Descriptor n, Word 2(MPU_RGDn.Word2)
 *    Access: Read/Write
 ************************************************************************/
/* @brief Read MPU Region Descriptor n, Word 2 (MPU_RGDn.Word2).
 * @param n: MPU_RGDn_t(0~7).
 * @ret_val 32bit(MPU_RGDnW2_...)
 * */
#define MPU_GET_RGDn_WORD2(n)    (MPU.RGD[n].WORD2.R)

/* @brief Write MPU Region Descriptor n, Word 2 (MPU_RGDn.Word2).
 * @param n: MPU_RGDn_t(0~7).
 *        val: 32bit(MPU_RGDnW2_...)
 * */
#define MPU_RGDn_WORD2_SET(n, val) (MPU.RGD[n].WORD2.R = (val)) /* PRQA S 3472 */


/************************************************************************
 *    MPU Region Descriptor n, Word 3(MPU_RGDn.Word3)
 *    Access: Read/Write
 ************************************************************************/
/* @brief   Read MPU Region Descriptor n, Word 3 (MPU_RGDn.Word3).
 * @note    bit[0:31] = {PID[0:7], PIDMASK[8:15], RESERVED[16:30], 
 *          VLD[31]};
 * @param   n: MPU_RGDn_t(0~7).
 * @ret_val 32bit
 * */
#define MPU_GET_RGDn_WORD3(n)    (MPU.RGD[n].WORD3.R)

/* @brief Write MPU Region Descriptor n, Word 3 (MPU_RGDn.Word3).
 * @note    bit[0:31] = {PID[0:7], PIDMASK[8:15], RESERVED[16:30], 
 *          VLD[31]};
 * @param n: MPU_RGDn_t(0~7).
 *        val: 32bit(VLD: MPU_RGDnW3_VLD_t)
 * */
#define MPU_RGDn_WORD3_SET(n, val) (MPU.RGD[n].WORD3.R = (val)) /* PRQA S 3472 */


/************************************************************************
 *    MPU Region Descriptor Alternate Access Control n (MPU_RGDAACn)
 *    = MPU Region Descriptor n, Word 2 (MPU_RGDn.Word2)
 *    Access: Read/Write
 ************************************************************************/
/* @brief   Descriptor Read MPU Region Descriptor n,Word 2(MPU_RGDn.Word2).
 * @param   n: MPU_RGDn_t(0~7).
 * @ret_val 32bits(MPU_RGDnW2_...)
 * */
#define MPU_GET_RGDAACn(n)       (MPU.RGDAAC[n].R)

/* @brief Descriptor Write MPU Region Descriptor n, Word 2(MPU_RGDn.Word2).
 * @param n: MPU_RGDn_t(0~7).
 *        val: 32bits(MPU_RGDnW2_...)
 * */
#define MPU_RGDAACn_SET(n, val) (MPU.RGDAAC[n].R = (val))



/************************************************************************
 *    Memory Protection Unit (MPU)
 *    Function declaration
 ************************************************************************/
extern void Enter_UserMode(void);
extern uint32_t MPU_RGDnWord0Word1_Set(uint8_t rgdNum, uint32_t startAddr, uint32_t endAddr);

#endif  /* MPU_LLD_H_ */
